package com.example.springstack.springsecurity.auth;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.exampl.springstack.common.GlobalConst;
import com.exampl.springstack.common.exceptionUtils.enums.ResultEnum;
import com.exampl.springstack.common.exceptionUtils.exception.SystemException;
import com.exampl.springstack.common.utils.LocalCacheUtils;
import com.example.springstack.springsecurity.entity.User;
import com.example.springstack.springsecurity.service.JwtService;
import com.example.springstack.springsecurity.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author Qiangfanghao\
 * 认证过滤器
 * jwt用户登录认证 并添加 认证权限
 */
@Slf4j
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UserService sysUserService;
    @Autowired
    private JwtService jwtService;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {

        //获取 认证头
        final String requestHeader = request.getHeader(GlobalConst.AUTHORIZATION);

        String authToken = null;
        if (StrUtil.isNotBlank(requestHeader) && requestHeader.startsWith(GlobalConst.AUTH_BEARER_PREFIX)) {
            //获取 认证token
            authToken = requestHeader.substring(GlobalConst.AUTH_BEARER_PREFIX.length());
        }


        //验证 token
        if (StrUtil.isNotBlank(authToken)) {

            //获取当前用户权限
            Authentication securityAuthentication = SecurityContextHolder.getContext().getAuthentication();
            //token合法 给用户添加 权限  如果用户已具有权限 则直接登录

            User jwtUser = null;
            //本地缓存获取 用户信息
            Object sysUserObj = LocalCacheUtils.get(authToken);

            if (sysUserObj instanceof User){
                jwtUser = (User) sysUserObj;
            }

            if (BeanUtil.isEmpty(jwtUser)) {
                //本地获取到的 用户与token不符合 清除登录权限缓存
                SecurityContextHolder.getContext().setAuthentication(null);
                log.debug("本地获取到的 用户与token不符合 清除登录权限缓存");
                throw  new SystemException(ResultEnum.USER_LOGIN_TIMEOUT);
            }

            //获取jwt所需ip
            String jwtCurrentIp = jwtService.getJwtCurrentIp(request);

            //校验 token 是否合法
            if (!jwtService.jwtAuthentication(authToken, jwtCurrentIp,jwtUser.getUsername())){
                log.warn("token 非法");
//                throw  new PEException(ResultEnum.USER_LOGIN_TIMEOUT);
            }

            if ( BeanUtil.isEmpty(securityAuthentication)){

                //获取登录用户权限
                List<GrantedAuthority> userAuthorities = this.sysUserService.getUserAuthorities(jwtUser.getUsername());
                jwtUser.setAuthorities(userAuthorities);

                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                        jwtUser, null, jwtUser.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }

        }
        chain.doFilter(request, response);
    }

}
